<?php
namespace app\admin\controller;

use app\admin\model\{AdminOperationLog,AdminUser};
use app\common\exception\BaseException;
use think\facade\Cache;
use think\facade\Env;

/**
 * 后台基类
 * Class Controller
 * @package app\admin\Controller
 */
class Controller extends Jwt
{
    protected $userinfo;
    // 初始化
    protected function initialize()
    {
        
        // 获取header头部中的Authorization
        $Authorization = isset($this->em_getallheaders()['Authorization'])?$this->em_getallheaders()['Authorization']:false;
        // 校验JWT
        $result = $this->verifyToken($Authorization);
        // 判断校验结果
        if($result === false || Cache::get('token_'.$result['userinfo']['admin_user_id']) !== $Authorization)
        {
            throw new BaseException(['code'=>-2,'msg' => '已失效']);
        }
        // 获取用户初始化数据,并赋值给全局变量
        $this->userinfo = (new AdminUser)->initUser($result['userinfo']['admin_user_id']);
        // 给缓存注入新的过期时间
        Cache::tag('cache')->set('token_'.$this->userinfo['admin_user_id'],$Authorization,1800);
        // 获取当前角色访问权限数组
        $admin_authority_menu_url = cache::get('admin_authority_menu_url_' . $this->userinfo['AdminRole']['admin_role_id']);
        //模块名
        $module = self::getCalledModule();
        //控制器名
        $controller = Request()->controller();
        //方法名
        $action = Request()->action();

        

        // 将链接转换成小写,校验是否有访问权限 原因看下方↓
        // if(!in_array(strtolower($module.'/'.$controller.'/'.$action),$admin_authority_menu_url))
        // {
        //     throw new BaseException(['code'=>-3,'msg' => '没有访问权限']);
        // }elseif(Env::get('operation_log.operation_log')) // 检查是否开启满足偷窥欲老板的需求功能
        // {
        //     if("admin/manager.index/index" !==  strtolower($module.'/'.$controller.'/'.$action))
        //     {
        //         // 只记录合法符合权限的请求,非法请求链接不记录(即没有通过权限访问校验不做记录,占内存)
        //         (new AdminOperationLog)->add(['admin_user_id'=>$this->userinfo['admin_user_id'],'admin_menu_id'=>array_search(strtolower($module.'/'.$controller.'/'.$action),$admin_authority_menu_url)]);
        //     }
        // }


        /**
         * 为什么改的原因,提供给你们参考下 PHP的in_array(),希望我的理解是对的.欢迎拍砖 ColinWoo<colinwoo@colinwoo.com>
         * PHP_FUNCTION(in_array)
         *   {
         *       php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
         *   }
         * static inline void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) {{{ 
         *   {
         *       zval *value,				//value to check for
         *           *array,				/* array to check in 
         *           *entry;				/* pointer to array entry
         *       zend_ulong num_idx;
         *       zend_string *str_idx;
         *       zend_bool strict = 0;		/* strict comparison or not
         *
         *       ZEND_PARSE_PARAMETERS_START(2, 3)
         *           Z_PARAM_ZVAL(value)
         *           Z_PARAM_ARRAY(array)
         *           Z_PARAM_OPTIONAL
         *           Z_PARAM_BOOL(strict)
         *       ZEND_PARSE_PARAMETERS_END();
         *
         *       if (strict) {
         *           if (Z_TYPE_P(value) == IS_LONG) {
         *               ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
         *                   ZVAL_DEREF(entry);
         *                   if (Z_TYPE_P(entry) == IS_LONG && Z_LVAL_P(entry) == Z_LVAL_P(value)) {
         *                       if (behavior == 0) {
         *                           RETURN_TRUE;
         *                       } else {
         *                           if (str_idx) {
         *                               RETVAL_STR_COPY(str_idx);
         *                           } else {
         *                               RETVAL_LONG(num_idx);
         *                           }
         *                           return;
         *                       }
         *                   }
         *               } ZEND_HASH_FOREACH_END();
         *           } else {
         *               ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
         *                   ZVAL_DEREF(entry);
         *                   if (fast_is_identical_function(value, entry)) {
         *                       if (behavior == 0) {
         *                           RETURN_TRUE;
         *                       } else {
         *                           if (str_idx) {
         *                               RETVAL_STR_COPY(str_idx);
         *                           } else {
         *                               RETVAL_LONG(num_idx);
         *                           }
         *                           return;
         *                       }
         *                   }
         *               } ZEND_HASH_FOREACH_END();
         *           }
         *       } else {
         *           if (Z_TYPE_P(value) == IS_LONG) {
         *               ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
         *                   if (fast_equal_check_long(value, entry)) {
         *                       if (behavior == 0) {
         *                           RETURN_TRUE;
         *                       } else {
         *                           if (str_idx) {
         *                               RETVAL_STR_COPY(str_idx);
         *                           } else {
         *                               RETVAL_LONG(num_idx);
         *                           }
         *                           return;
         *                       }
         *                   }
         *               } ZEND_HASH_FOREACH_END();
         *           } else if (Z_TYPE_P(value) == IS_STRING) {
         *               ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
         *                   if (fast_equal_check_string(value, entry)) {
         *                       if (behavior == 0) {
         *                           RETURN_TRUE;
         *                       } else {
         *                           if (str_idx) {
         *                               RETVAL_STR_COPY(str_idx);
         *                           } else {
         *                               RETVAL_LONG(num_idx);
         *                           }
         *                           return;
         *                       }
         *                   }
         *               } ZEND_HASH_FOREACH_END();
         *           } else {
         *               ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
         *                   if (fast_equal_check_function(value, entry)) {
         *                       if (behavior == 0) {
         *                           RETURN_TRUE;
         *                       } else {
         *                           if (str_idx) {
         *                               RETVAL_STR_COPY(str_idx);
         *                           } else {
         *                               RETVAL_LONG(num_idx);
         *                           }
         *                           return;
         *                      }
         *                   }
         *               } ZEND_HASH_FOREACH_END();
         *            }
         *        }
         *
         *       RETURN_FALSE;
         *   }
         */

        // 1.2版本,优化鉴权机制
        if(isset($admin_authority_menu_url[strtolower($module.'/'.$controller.'/'.$action)]))
        {
            if(Env::get('operation_log.operation_log')) // 检查是否开启满足偷窥欲老板的需求功能(故意不写在后台管理.有要求再去配置文件增加就好)
            {
                // 获取对应菜单ID,既然进的来权限管理,就说明这个数组键名是有的,可以直接取值
                $admin_menu_id = $admin_authority_menu_url[strtolower($module.'/'.$controller.'/'.$action)];
                // 只记录合法符合权限的请求,非法请求链接不记录(即没有通过权限访问校验不做记录-脏数据太多,影响数据表查询速度)
                (new AdminOperationLog)->add(['admin_user_id'=>$this->userinfo['admin_user_id'],'admin_menu_id'=>$admin_menu_id]);
            }
        }else
        {
            // 没有访问权限
            throw new BaseException(['code'=>-3,'msg' => '没有访问权限']);
        }
    }

    /**
     * 获取当前调用的模块名称
     * 例如：admin, api, store, task
     * @return string|bool
     */
    protected static function getCalledModule()
    {
        if (preg_match('/app\\\(\w+)/', get_called_class(), $class)) {
            return $class[1];
        }
        return false;
    }

}